﻿using System;
using System.IO;
using System.Text;
using System.Threading;
using WeDonekRpc.Helper;

namespace WeDonekRpc.HttpApiGateway.FileUp.Model
{
    internal class UpFileForm
    {
        /// <summary>
        /// 文件名称
        /// </summary>
        public string fileName;
        /// <summary>
        /// 文件大小
        /// </summary>
        public long fileSize;
        /// <summary>
        /// 文件MD5
        /// </summary>
        public string fileMd5;
        /// <summary>
        /// 块大小
        /// </summary>
        public int blockSize;
        /// <summary>
        /// 已上传大小
        /// </summary>
        public long alreadyUp;

        public byte[] cs;
        public void Create(FileStream stream)
        {
            this._InitCs();
            this.Write(stream);
        }
        public void Reset(FileStream stream)
        {
            this.alreadyUp = 0;
            this.cs.Initialize();
            this.Write(stream);
        }
        private void _InitCs()
        {
            int len = (int)(this.fileSize / this.blockSize);
            if (this.fileSize % this.blockSize != 0)
            {
                len += 1;
            }
            this.cs = new byte[len];
        }
        public byte[] ToByte()
        {
            int len = 52 + this.cs.Length;
            byte[] bytes = new byte[len];
            BitHelper.WriteByte(this.fileSize, bytes, 0);
            BitHelper.WriteByte(this.blockSize, bytes, 8);
            BitHelper.WriteByte(this.alreadyUp, bytes, 12);
            Encoding.UTF8.GetBytes(this.fileMd5, 0, 32, bytes, 20);
            Buffer.BlockCopy(this.cs, 0, bytes, 52, this.cs.Length);
            return bytes;
        }
        public void Write(FileStream stream)
        {
            byte[] datas = this.ToByte();
            stream.Position = 0;
            stream.Write(datas, 0, datas.Length);
            stream.Flush();
        }
        public void Init(FileStream stream)
        {
            stream.Position = 0;
            byte[] bytes = new byte[52];
            stream.Read(bytes, 0, bytes.Length);
            this.fileSize = BitConverter.ToInt64(bytes);
            this.blockSize = BitConverter.ToInt32(bytes, 8);
            this.alreadyUp = BitConverter.ToInt64(bytes, 12);
            this.fileMd5 = Encoding.UTF8.GetString(bytes, 20, 32);
            this._InitCs();
            stream.Read(this.cs, 0, this.cs.Length);
        }
        public bool CheckIsComplate()
        {
            return this.fileSize == this.alreadyUp;

        }
        public bool WriteAlreadyUp(FileStream stream, int index, int size, byte cs)
        {
            long total = Interlocked.Add(ref this.alreadyUp, size);
            byte[] val = BitConverter.GetBytes(total);
            this.cs[index] = cs;
            stream.Position = 12;
            stream.Write(val, 0, 8);
            stream.Position = 52 + index;
            stream.WriteByte(cs);
            stream.Flush();
            if(total > this.fileSize)
            {
                throw new ErrorException("gateway.http.up.file.error");
            }
            return total == this.fileSize;
        }

    }
}
